package smlab.view.ui.tree
{
	import avmplus.getQualifiedClassName;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.utils.getDefinitionByName;
	
	import mx.charts.AreaChart;
	
	import smlab.utils.DisplayObjectUtil;
	
	/**
	 * 树形组件
	 * @author simon
	 * 
	 */
	public class Tree_SM extends Sprite
	{
		public static const NODE_STATE_OPEN:String="node_state_open";//节点状态：关闭或者打开
		public static const NODE_STATE_CLOSE:String="node_state_close";//各节点所有数据
		public var maxLevel:int;//最大层级数,从0开始

/*
		<nodes>
			<node id="0" level="0" title="你好1">
				<node id="1" level="1" title="好呀">
					<node id="45" level="2" title="你好5">
						<node id="2" level="3" title="你好4"/>
					</node>
				</node>
				<node id="2" level="1" title="hello"/>
			</node>
			<node id="8" level="0" title="你好3"/>
		</nodes>
*/
		private var dataProvider_:XML;//各节点所有数据（包含层级关系）必须是XML,格式如上
		private var allNodeArr_:Array=[];//按顺序存放所有节点数据，没有层级关系
		private var allNodeWithLevelArr_:Array=[];//按层级关系存放所有节点数据
		private var widthTree_:Number;//树形组件整体宽度
		private var heightTree_:Number;//树形组件整体高度
		private var nodeClass_:Class;//节点的类
		private var yGapArr_:Array;//各个节点的行间距
		private var xGapArr_:Array;//各个节点的X轴缩进距离
		private var nodeContainer:Sprite;//节点的类
		
		/**
		 * 构造函数
		 * @param w				树形组件宽度
		 * @param h				树形组件高度
		 * @param nodeClass		节点的类
		 * 
		 * @param nodeYGapArr	各个层级的节点的行间距；如：[5,3,2]代表第一层级节点的行间距为5
		 * 						第二层级节点的行间距为3，第三层级节点的行间距为2;
		 * 
		 * @param nodeXGapArr	各个层级的节点的X轴缩进距离；如：[0,10,20]代表第一层级节点的X轴缩进距离为0
		 * 						第二层级节点的X轴缩进距离为10，第三层级节点的X轴缩进距离为20;
		 * 
		 */
		public function Tree_SM(w:Number=0,h:Number=0,nodeClass:Class=null,yGapArr:Array=null,xGapArr:Array=null)
		{
			super();
			nodeClass_=nodeClass;
			yGapArr_=yGapArr;
			xGapArr_=xGapArr;
			this.widthTree=w;
			this.heightTree=h;
			nodeContainer=new Sprite;
			addChild(nodeContainer);
			updateWH();
			
			addEventListener(TreeEvent_SM.CLICK_NODE,onNodeClick);
		}
		
		/**
		 * 更新整个树形组件自定义宽高
		 * 
		 */
		private function updateWH():void{
			var r:Rectangle=new Rectangle(0,0,widthTree,heightTree);
			nodeContainer.scrollRect=r;
		}
		
		public function set widthTree(n:Number):void
		{
			widthTree_=n;
		}
		
		public function get widthTree():Number
		{
			return widthTree_;
		}
		
		public function set heightTree(n:Number):void
		{
			heightTree_=n;
		}
		
		public function get heightTree():Number
		{
			return heightTree_;
		}
		
		/**
		 * @param value 数据源只能是 XML
		 *
		 */
		public function set dataProvider(value:XML):void {
			dataProvider_ = value;
			parseXMLDataProvider(dataProvider);
		}
		
		public function get dataProvider():XML
		{
			return dataProvider_;
		}
		
		/**
		 * 把 XML 形式的树形数据解析成数组
		 * @param dataXML
		 * 
		 */
		private function parseXMLDataProvider(dataXML:XML):void
		{
			this.allNodeWithLevelArr_ = [];
			
			for each (var node:XML in dataXML.elements())
			{
				this.allNodeWithLevelArr_.push(this.parseXMLNode(null, node));
			}
			
			this.drawUI();
		}
		
		/**
		 * 将 XML 递归解析为树形节点
		 * @param parentNode
		 * @param data
		 * @return 
		 * 
		 */
		private function parseXMLNode(parentNode:TreeNode_SM, data:XML):TreeNode_SM 
		{
			var node:TreeNode_SM = new nodeClass_;
			node.id = data.@id;
			node.level = data.@level;
			node.title = data.@title;
			node.xGap=this.xGapArr_[node.level];
			node.yGap=this.yGapArr_[node.level];
			
			for each (var attribute:XML in data.attributes()) {
				var attriName:String = String(attribute.name());
				var attriValue:String = String(attribute.toString());
				
				if (attriName != "index" && attriName != "level" && attriName != "title") {
					node.data[attriName] = attriValue;
				}
			}
			
			if (parentNode != null) {
				node.parentNode = parentNode;
			}
			
			//判断是否有子节点
			if (data.elements().length() > 0)
			{
				//还有子节点
				node.childNodes = [];
				var level:uint=node.level
				++level;
				maxLevel = level;
				
				for each (var xmlNode:XML in data.elements()) {
					var cn:TreeNode_SM=this.parseXMLNode(node,xmlNode);
					node.childNodes.push(cn);
				}
			}
			node.data=null;//这里必须设置一次，等于调用“更新”
			node.drawChildrenDisplay();
			allNodeArr_.push(node);
			
			return node;
		}
		
		/**
		 * 再次递归解析所有节点
		 * @param level
		 * @param parentNode
		 * @param node
		 * @return 
		 * 
		 */
//		private function parseTreeNode(level:int, parentNode:TreeNode_SM, node:TreeNode_SM):TreeNode_SM 
//		{
//			var treeNode:TreeNode_SM;
//			
//			if (this.nodeClass_ == null) {
//				treeNode = new TreeNode_SM();
//			} else {
//				var renderer:Class = getDefinitionByName(getQualifiedClassName(this.nodeClass_))as Class;
//				treeNode = new renderer() as TreeNode_SM;
//			}
//			
//			if (parentNode != null) {
//				treeNode.parentNode = parentNode;
//			}
//			treeNode.level = level;
//			
//			if (node.childNodes) {
//				treeNode.childNodes = [];
//				++level;
//				this.maxLevel = level;
//				
//				for each (var node2:TreeNode_SM in node.childNodes) {
//					treeNode.childNodes.push(this.parseTreeNode(level, treeNode,node2));
//				}
//				treeNode.drawChildrenDisplay();
//			}
//			
//			this.allNodeArr_.push(treeNode);
//			return treeNode;
//			
//		}
		
		private function drawUI():void
		{
			DisplayObjectUtil.removeAllChild(nodeContainer);
			
			for (var i:int = 0; i < this.allNodeWithLevelArr_.length; i++) {
				var node:TreeNode_SM = this.allNodeWithLevelArr_[i];
				this.nodeContainer.addChild(node);
			}
			
			this.drawLayout();
		}
		
		/**
		 *	绘制布局
		 * 这里设置下最根节点的布局
		 * 实际上在node中还要设置下各个项的子项位置,用的是同样的方法
		 * 如果在这里写一个递归统一设置下布局也可以，但递归调用消耗还是比较大的
		 *
		 */
		private function drawLayout():void
		{
			for (var i:int = 0; i < allNodeWithLevelArr_.length; i++)
			{
				var node:TreeNode_SM = allNodeWithLevelArr_[i];
				
				if(xGapArr_[0]!=null){
					node.x=xGapArr_[0];
				}
				
				if (i == 0) {
					node.y = 0;
				} else {
					node.y = allNodeWithLevelArr_[i - 1].y + allNodeWithLevelArr_[i -1].height+yGapArr_[0];
				}
			}
		}
		
		private function onNodeClick(e:TreeEvent_SM):void
		{
			drawLayout();
			
			for each (var node:TreeNode_SM in allNodeArr_) {
				if (e.node != node) {
					node.selected=false;
				}
			}
		}
	}
}